/**
* @file frm_mange.c
* @brief FRAM manage
* @author xy
* @version 1.0
* @date 2024-11-12
*/
#include "fram_mange.h"
#include <stdlib.h>

#define FRAM_MALLOC malloc
#define FRAM_FREE free

void fram_read_dev(unsigned int addr, unsigned char *data, unsigned int len)
{
    /* user code */
}

void fram_write_dev(unsigned int addr, unsigned char *data, unsigned int len)
{
    /* user code */
}

/*  */
void fmmemfill(void *pout, unsigned char dat, unsigned int len)
{
    unsigned char *poutt;
    unsigned int icnt;
    poutt = (unsigned char *) pout;
    for (icnt = 0; icnt < len; icnt++)
    {
        poutt[icnt] = dat;
    }
}

/*生成校验用数据 */
unsigned char calc_ch_data_m0(unsigned char *pdin, unsigned char *pdch, uint32_t len)
{
    uint32_t icnt;
    for (icnt = 0; icnt < len; icnt++)
    {
        pdch[icnt] = (~(pdin[icnt])) & 0xff;
    }
    return 0;
}

/* 数据比较 */
uint32_t DataCheck(uint8_t *pf1, uint8_t *pf2, uint32_t count)
{
    uint32_t i;
    for (i = 0; i < count; i++)
    {
        if (pf1[i] != pf2[i])
        {
            return 1;
        }
    }
    return 0;
}

/* 使用校验数据检查数据 返回0：无错误 其他：存在错误*/
unsigned char check_data_m0(unsigned char *pdata, unsigned char *pdch, uint32_t len)
{
    uint32_t icnt;
    for (icnt = 0; icnt < len; icnt++)
    {
        if (((~pdch[icnt]) & 0xff) != pdata[icnt])
        {
            return 1;
        }
    }
    return 0;
}

/* 内存数据复制
    *pout       ：数据目标指针
    *pin        ：数据来源指针
     len        ：数据长度                          */
void fdmemcpy(void *pout, void *pin, unsigned int len)
{
    unsigned char *pint;
    unsigned char *poutt;
    int icnt;
    pint = (unsigned char *) pin;
    poutt = (unsigned char *) pout;
    for (icnt = 0; icnt < len; icnt++)
    {
        poutt[icnt] = pint[icnt];
    }
}


int framwrite(struct FRAM_DATA_INFO_S *framinfo, unsigned int addr, unsigned char *data, unsigned int len)
{
    int ret = 0;
    unsigned char *pdtmpch0 = NULL;

    pdtmpch0 = (unsigned char *) FRAM_MALLOC(len);
    if (pdtmpch0 != NULL)
    {
        calc_ch_data_m0(data, pdtmpch0, len);
        fram_write_dev(framinfo->addrstart + addr, data, len);
        fram_write_dev(framinfo->addrstart + (framinfo->datlen * 1) + addr, pdtmpch0, len);
        fram_write_dev(framinfo->addrstart + (framinfo->datlen * 2) + addr, data, len);
        fram_write_dev(framinfo->addrstart + (framinfo->datlen * 3) + addr, pdtmpch0, len);
    }
    if (pdtmpch0 != NULL)
    {
        FRAM_FREE(pdtmpch0);
        pdtmpch0 = NULL;
    }

    return ret;
}

int framread(struct FRAM_DATA_INFO_S *framinfo, unsigned int addr, unsigned char *data, unsigned int len)
{
    int ret = 0;
    unsigned char *pdtmp0 = NULL;
    unsigned char *pdtmpch0 = NULL;

    pdtmp0 = (unsigned char *) FRAM_MALLOC(len);
    pdtmpch0 = (unsigned char *) FRAM_MALLOC(len);
    if ((pdtmp0 != NULL) && (pdtmpch0 != NULL))
    {
        fram_read_dev(framinfo->addrstart + addr, pdtmp0, len);
        fram_read_dev(framinfo->addrstart + (framinfo->datlen * 1) + addr, pdtmpch0, len);
        if (!check_data_m0(pdtmp0, pdtmpch0, len))
        {
            fdmemcpy(data, pdtmp0, len);
        } else
        {
            fram_read_dev(framinfo->addrstart + (framinfo->datlen * 2) + addr, pdtmp0, len);
            fram_read_dev(framinfo->addrstart + (framinfo->datlen * 3) + addr, pdtmpch0, len);
            if (!check_data_m0(pdtmp0, pdtmpch0, len))
            {
                fdmemcpy(data, pdtmp0, len);
            } else
            {
                ret = -2;
            }
        }
    } else
    {
        ret = -1;
    }
    if (pdtmp0 != NULL)
    {
        FRAM_FREE(pdtmp0);
        pdtmp0 = NULL;
    }
    if (pdtmpch0 != NULL)
    {
        FRAM_FREE(pdtmpch0);
        pdtmpch0 = NULL;
    }

    return ret;
}
